﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Web;
using Eksponent.CropUp.Client;
using Eksponent.CropUp.Config;

namespace Eksponent.CropUp.JavaScript
{
    /// <summary>
    /// Use this class to convert server side <see cref="ImageCropData"/> to javascript representation and vice versa
    /// </summary>
    public class ClientDataConverter
    {
        public string ImagePath { get; set; }
        
        public ClientDataConverter(string imagePath)
        {
            ImagePath = imagePath;
        }

        public static ClientCropInfo FromCropInfo(CropInfo ci, int originalWidth = 0, int originalHeight = 0)
        {
            if (!ci.Relative)
            {
                ci = ci.ToRelative(originalWidth, originalHeight);
            }

            return new ClientCropInfo
            {
                manual = !ci.Calculated,
                gravity = ci.Gravity.HasValue ? new double[] { ci.Gravity.Value.X, ci.Gravity.Value.Y } : null,
                box = new double[] { ci.TopLeft.X, ci.TopLeft.Y, ci.BottomRight.X, ci.BottomRight.Y }
            };
        }

        public static CropInfo FromClientCropInfo(ClientCropInfo cci)
        {
            return new CropInfo
            {
                Relative = true,
                Calculated = !cci.manual,
                Gravity = cci.gravity == null || cci.gravity.Length == 0 ? (PointF?)null : new PointF((float)(cci.gravity[0]), (float)(cci.gravity[1])),
                TopLeft = new PointF((float)cci.box[0], (float)cci.box[1]),
                BottomRight = new PointF((float)cci.box[2], (float)cci.box[3])
            };
        }

        public void Save(string postedValue)
        {
            if (ImagePath != null && !string.IsNullOrEmpty(postedValue))
            {
                var data = JsonHelper.Serializer.Deserialize<ClientCropData>(postedValue);
                var cropData = new ImageCropData()
                {
                    Default = FromClientCropInfo(data.@default),
                    ManualCroppings = new Dictionary<string, CropInfo>()
                };
                
                foreach (var mc in data.croppings.Where(mc => mc.Value.manual))
                {
                    cropData.ManualCroppings[mc.Key] = FromClientCropInfo(mc.Value);
                }

                CropUp.CropDataProvider.SaveCropData(ImagePath, cropData);
                CropUp.Dialect.ClearCache(ImagePath);
            }
        }

        public CropperData GetCropperData(CropperData posted = null)
        {
            if (ImagePath != null)
            {               
                if (!ImagePath.StartsWith("~")) ImagePath = "~" + ImagePath;
                var size = posted != null ? new Size(posted.originalWidth, posted.originalHeight) : CropUp.Dialect.GetImageSize(ImagePath);
                var data = CropUp.CropDataProvider.GetCropData(ImagePath) ?? new ImageCropData();

                //Suggest defaults
                if (data.Default == null) data.Default = CropInfo.Default;
                if (data.ManualCroppings == null) data.ManualCroppings = new Dictionary<string, CropInfo>();

                if (posted != null) data.Default = FromClientCropInfo(posted.data.@default);
                

                var clientData = new CropperData
                {
                    originalWidth = size.Width,
                    originalHeight = size.Height,
                    data = new ClientCropData
                    {
                        @default = FromCropInfo(data.Default, size.Width, size.Height),
                        croppings = new Dictionary<string, ClientCropInfo>()
                    },
                    croppings = new Dictionary<string, ClientCropSettings>()
                };

                foreach (var crop in CropUp.Configuration.CropInfos.Cast<CropInfoElement>().ToArray())
                {
                    clientData.croppings[crop.Alias] = new ClientCropSettings
                    {
                        width = crop.Width,
                        height = crop.Height,
                        alias = crop.Alias,
                        label = crop.Name
                    };
                }

                foreach (var mc in data.ManualCroppings)
                {
                    if (!mc.Value.Calculated)
                    {
                        clientData.data.croppings[mc.Key] = FromCropInfo(mc.Value, size.Width, size.Height);
                    }
                }

                return clientData;
            }

            return null;
        }
    }
}
